package user

import (
	"encoding/json"
	"fmt"
	"time"

	"ser1/app/slog"
	"ser1/config"
	"ser1/redisdb"
	"ser1/utils"

	"github.com/gin-gonic/gin"
)

// AddUser godoc
// @Summary 添加用户
// @Description 添加新用户
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param user body User true "用户信息"
// @Success 200 {object} gin.H
// @Router /users/add [post]
func AddUser(c *gin.Context) {
	var user User
	if err := c.ShouldBindJSON(&user); err != nil {
		utils.ResponseError(c, 1, "参数错误")
		return
	}
	user.Token = ""
	user.Password = utils.CreateSecret(user.Password, getPASS_SECRET())
	if err := DB().Create(&user).Error; err != nil {
		utils.ResponseError(c, 1, "添加失败")
		return
	}
	utils.ResponseSuccess(c, user.ID)
}

// UpdateUser godoc
// @Summary 更新用户
// @Description 更新用户信息
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param id path int true "用户ID"
// @Param user body User true "用户信息"
// @Success 200 {object} gin.H
// @Router/users/{id} [put]
func UpdateUser(c *gin.Context) {
	var user User
	if err := c.ShouldBindJSON(&user); err != nil {
		utils.ResponseError(c, 1, "参数错误")
		return
	}
	slog.AddOptions(c, "更新用户", user)
	err := DB().Model(&User{}).Where("id = ?", user.ID).Omit("token", "password", "username").Updates(&user)
	if err != nil {
		utils.ResponseError(c, 1, "更新失败")
		return
	}
	utils.ResponseSuccess(c, 1)
}

// GetUsers godoc
// @Summary 获取用户列表
// @Description 获取所有用户信息
// @Tags 用户管理
// @Accept json
// @Produce json
// @Success 200 {array} User
// @Router /users [get]
func GetUsers(c *gin.Context) {
	var dto utils.PaginationDTO
	if err := c.ShouldBindQuery(&dto); err != nil {
		utils.ResponseError(c, 1, "参数错误")
		return
	}
	dto.SetDefaults()
	query := DB().Model(&User{})
	if dto.Search != "" {
		query.Where("username LIKE ? OR second_name LIKE ?", "%"+dto.Search+"%", "%"+dto.Search+"%")
	}
	if dto.Name != "" {
		query.Where("username = ? OR second_name = ?", dto.Name, dto.Name)
	}
	if dto.TagId != 0 {
		query.Where("depart_id = ?", dto.TagId)
	}
	offset := (dto.Page - 1) * dto.Size
	limit := dto.Size
	var total int64
	var user []User
	query.Count(&total)
	query.Offset(offset).Limit(limit).Find(&user)
	utils.ResponseSuccess(c, gin.H{
		"total": total,
		"data":  user,
	})
}

// GetUser godoc
// @Summary 获取用户详情
// @Description 获取指定用户信息
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param id path int true "用户ID"
// @Success 200 {object} User
// @Router /users/{id} [get]
func GetUser(c *gin.Context) {
	id := c.Param("id")
	if err := DB().Where("id = ?", id).First(&User{}).Error; err != nil {
		utils.ResponseError(c, 1, "获取用户失败")
		return
	}
	utils.ResponseSuccess(c, User{})
}

// UpdateUserMeta godoc
// @Summary 更新用户元数据
// @Description 更新用户元数据信息
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param user_meta body []UserMeta true "用户元数据"
// @Success 200 {object} gin.H
// @Router /users/meta [post]
func UpdateUserMeta(c *gin.Context) {
	var userMeta []UserMeta
	if err := c.ShouldBindJSON(&userMeta); err != nil {
		utils.ResponseError(c, 1, "参数错误")
		return
	}
	if err := DB().Create(&userMeta).Error; err != nil {
		utils.ResponseError(c, 1, "更新失败")
		return
	}
	utils.ResponseSuccess(c, 1)
}

type LoginDto struct {
	Login    string `json:"login" binding:"required"`
	Method   string `json:"method" binding:"required"`
	Password string `json:"password" binding:"required"`
}

// Login godoc
// @Summary 用户登录
// @Description 用户登录接口
// @Tags 用户管理
// @Accept json
// @Produce json
// @Param login body LoginDto true "登录信息"
// @Success 200 {object} gin.H
// @Router /login [post]
func Login(c *gin.Context) {
	var login LoginDto
	if err := c.ShouldBindJSON(&login); err != nil {
		utils.ResponseError(c, 1, "参数错误")
		return
	}
	slog.AddOptions(c, "登录操作", login)
	pass := utils.CreateSecret(login.Password, getPASS_SECRET())
	
	// 尝试从缓存获取用户信息
	var u User
	
	// 构建缓存键
	var cacheKey string
	if login.Method == "phone" {
		cacheKey = fmt.Sprintf("user:phone:%s", login.Login)
	} else {
		cacheKey = fmt.Sprintf("user:username:%s", login.Login)
	}
	
	// 尝试从Redis获取缓存的用户数据
	userFoundInCache := false
	if cachedUser, err := redisdb.Get(cacheKey); err == nil {
		if err := json.Unmarshal([]byte(cachedUser), &u); err == nil && u.Password == pass {
			// 验证通过，直接使用缓存中的用户数据
			userFoundInCache = true
		}
	}
	
	// 如果缓存未命中或密码不匹配，则查询数据库
	if !userFoundInCache {
		query := DB().Where("password = ? AND status = ?", pass, 1)
		
		if login.Method == "phone" {
			query = query.Where("phone = ?", login.Login)
		} else {
			query = query.Where("username = ?", login.Login)
		}
		
		result := query.First(&u)
		
		// 如果查询失败
		if result.Error != nil {
			utils.ResponseError(c, 1, "用户名或密码错误")
			return
		}
		
		// 如果没有找到用户
		if u.ID == 0 {
			utils.ResponseError(c, 1, "用户名或密码错误")
			return
		}
		
		// 将用户信息缓存到Redis (有效期1小时)
		userBytes, _ := json.Marshal(u)
		redisdb.Set(cacheKey, string(userBytes), time.Hour)
	}

	TOKEN_EXPIRE_HOUR := config.GetField("TOKEN_EXPIRE_HOUR")
	hours := utils.StrToInt(TOKEN_EXPIRE_HOUR)

	// 修复：将 u.ID 转换为字符串，并正确处理 CreateJwt 返回的两个值
	token, err := utils.CreateJwt(utils.UintToString(u.ID), uint(hours))
	if err != nil {
		utils.ResponseError(c, 1, "生成令牌失败")
		return
	}
	//获取当前时间
	now := time.Now()
	//对时间进行计算
	expireTime := now.Add(time.Hour * time.Duration(hours))
	//转字符串
	expireTimeStr := utils.TimeToStr(expireTime.Unix())
	DB().Model(&User{}).Where("id = ?", u.ID).Update("token", token).Update("expire", expireTimeStr)
	redisdb.SetUserTk(u.ID, token, time.Hour*time.Duration(hours))
	utils.ResponseSuccess(c, gin.H{
		"userId": u.ID,
		"token":  token,
	})
}
func test(c *gin.Context) {
	utils.ResponseSuccess(c, utils.GetUserId(c))
}
